From: kaf24@scramble.cl.cam.ac.uk Date: Wed, 30 Jun 2004 15:31:23 +0000 (+0000) Subject: bitkeeper revision 1.1041.2.1 (40e2dccbwLPMSsarwzAscW72tSfuEg) X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~18078^2~1 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=5018bf31377c6416f0c5a250a0afdabdc810ef2b;p=xen.git bitkeeper revision 1.1041.2.1 (40e2dccbwLPMSsarwzAscW72tSfuEg) Add resource tracking for pfn mappings in libxc. --- diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c index ceace01b00..c2228b5e9e 100644 --- a/tools/libxc/xc_linux_build.c +++ b/tools/libxc/xc_linux_build.c @@ -18,7 +18,7 @@ static int readelfimage_base_and_size(char *elfbase, unsigned long *pkernstart, unsigned long *pkernend, unsigned long *pkernentry); -static int loadelfimage(char *elfbase, int pmh, unsigned long *parray, +static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray, unsigned long vstart); static long get_tot_pages(int xc_handle, u32 domid) @@ -53,7 +53,7 @@ static int get_pfn_list(int xc_handle, return (ret < 0) ? -1 : op.u.getmemlist.num_pfns; } -static int copy_to_domain_page(int pm_handle, +static int copy_to_domain_page(void *pm_handle, unsigned long dst_pfn, void *src_page) { @@ -86,7 +86,8 @@ static int setup_guestos(int xc_handle, extended_start_info_t *start_info; shared_info_t *shared_info; mmu_t *mmu = NULL; - int pm_handle=-1, rc; + void *pm_handle=NULL; + int rc; unsigned long nr_pt_pages; unsigned long ppt_alloc; @@ -165,7 +166,7 @@ static int setup_guestos(int xc_handle, v_start, v_end); printf(" ENTRY ADDRESS: %08lx\n", vkern_entry); - if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 ) + if ( (pm_handle = init_pfn_mapper((domid_t)dom)) == NULL ) goto error_out; if ( (page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL ) @@ -307,7 +308,7 @@ static int setup_guestos(int xc_handle, error_out: if ( mmu != NULL ) free(mmu); - if ( pm_handle >= 0 ) + if ( pm_handle != NULL ) (void)close_pfn_mapper(pm_handle); if ( page_array != NULL ) free(page_array); @@ -629,7 +630,7 @@ static int readelfimage_base_and_size(char *elfbase, return 0; } -static int loadelfimage(char *elfbase, int pmh, unsigned long *parray, +static int loadelfimage(char *elfbase, void *pmh, unsigned long *parray, unsigned long vstart) { Elf_Ehdr *ehdr = (Elf_Ehdr *)elfbase; @@ -649,11 +650,11 @@ static int loadelfimage(char *elfbase, int pmh, unsigned long *parray, { pa = (phdr->p_vaddr + done) - vstart; va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]); - va += pa & (PAGE_SIZE-1); chunksz = phdr->p_filesz - done; if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) ) chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1)); - memcpy(va, elfbase + phdr->p_offset + done, chunksz); + memcpy(va + (pa & (PAGE_SIZE-1)), + elfbase + phdr->p_offset + done, chunksz); unmap_pfn(pmh, va); } @@ -661,11 +662,10 @@ static int loadelfimage(char *elfbase, int pmh, unsigned long *parray, { pa = (phdr->p_vaddr + done) - vstart; va = map_pfn_writeable(pmh, parray[pa>>PAGE_SHIFT]); - va += pa & (PAGE_SIZE-1); chunksz = phdr->p_memsz - done; if ( chunksz > (PAGE_SIZE - (pa & (PAGE_SIZE-1))) ) chunksz = PAGE_SIZE - (pa & (PAGE_SIZE-1)); - memset(va, 0, chunksz); + memset(va + (pa & (PAGE_SIZE-1)), 0, chunksz); unmap_pfn(pmh, va); } } diff --git a/tools/libxc/xc_linux_restore.c b/tools/libxc/xc_linux_restore.c index badba75162..f091914dba 100644 --- a/tools/libxc/xc_linux_restore.c +++ b/tools/libxc/xc_linux_restore.c @@ -19,7 +19,6 @@ #define DPRINTF(_f, _a...) ((void)0) #endif - static int get_pfn_list(int xc_handle, u32 domain_id, unsigned long *pfn_buf, @@ -53,23 +52,28 @@ static int get_pfn_list(int xc_handle, * @param ioctxt i/o context * @return 0 on success, non-zero on error. */ -static int read_vmconfig(XcIOContext *ioctxt){ +static int read_vmconfig(XcIOContext *ioctxt) +{ int err = -1; - if(xcio_read(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n))){ + + if ( xcio_read(ioctxt, &ioctxt->vmconfig_n, sizeof(ioctxt->vmconfig_n)) ) goto exit; - } + ioctxt->vmconfig = malloc(ioctxt->vmconfig_n + 1); - if(!ioctxt->vmconfig) goto exit; - if(xcio_read(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n)){ + if ( ioctxt->vmconfig == NULL ) goto exit; - } + + if ( xcio_read(ioctxt, ioctxt->vmconfig, ioctxt->vmconfig_n) ) + goto exit; + ioctxt->vmconfig[ioctxt->vmconfig_n] = '\0'; err = 0; + exit: - if(err){ - if(ioctxt->vmconfig){ + if ( err ) + { + if ( ioctxt->vmconfig != NULL ) free(ioctxt->vmconfig); - } ioctxt->vmconfig = NULL; ioctxt->vmconfig_n = 0; } @@ -126,12 +130,13 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) mmu_t *mmu = NULL; - int pm_handle = -1; + void *pm_handle = NULL; /* used by debug verify code */ unsigned long buf[PAGE_SIZE/sizeof(unsigned long)]; - if ( mlock(&ctxt, sizeof(ctxt) ) ) { + if ( mlock(&ctxt, sizeof(ctxt) ) ) + { /* needed for when we do the build dom0 op, but might as well do early */ PERROR("Unable to mlock ctxt"); @@ -140,24 +145,28 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* Start writing out the saved-domain record. */ if ( xcio_read(ioctxt, signature, 16) || - (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) { + (memcmp(signature, "LinuxGuestRecord", 16) != 0) ) + { xcio_error(ioctxt, "Unrecognised state format -- no signature found"); goto out; } if ( xcio_read(ioctxt, name, sizeof(name)) || xcio_read(ioctxt, &nr_pfns, sizeof(unsigned long)) || - xcio_read(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ) { + xcio_read(ioctxt, pfn_to_mfn_frame_list, PAGE_SIZE) ) + { xcio_error(ioctxt, "Error reading header"); goto out; } - if(read_vmconfig(ioctxt)){ + if ( read_vmconfig(ioctxt) ) + { xcio_error(ioctxt, "Error writing vmconfig"); goto out; } - for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) { + for ( i = 0; i < MAX_DOMAIN_NAME; i++ ) + { if ( name[i] == '\0' ) break; if ( name[i] & 0x80 ) { @@ -167,7 +176,8 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) } name[MAX_DOMAIN_NAME-1] = '\0'; - if ( nr_pfns > 1024*1024 ) { + if ( nr_pfns > 1024*1024 ) + { xcio_error(ioctxt, "Invalid state file -- pfn count out of range"); goto out; } @@ -177,19 +187,23 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) pfn_type = calloc(1, 4 * nr_pfns); region_mfn = calloc(1, 4 * MAX_BATCH_SIZE); - if ( (pfn_to_mfn_table == NULL) || (pfn_type == NULL) || - (region_mfn == NULL) ) { + if ( (pfn_to_mfn_table == NULL) || + (pfn_type == NULL) || + (region_mfn == NULL) ) + { errno = ENOMEM; goto out; } - if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) { + if ( mlock(region_mfn, 4 * MAX_BATCH_SIZE ) ) + { xcio_error(ioctxt, "Could not mlock region_mfn"); goto out; } /* Set the domain's name to that from the restore file */ - if ( xc_domain_setname( xc_handle, dom, name ) ) { + if ( xc_domain_setname( xc_handle, dom, name ) ) + { xcio_error(ioctxt, "Could not set domain name"); goto out; } @@ -208,24 +222,26 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) op.cmd = DOM0_GETDOMAININFO; op.u.getdomaininfo.domain = (domid_t)dom; op.u.getdomaininfo.ctxt = NULL; - if ( do_dom0_op(xc_handle, &op) < 0 ) { + if ( do_dom0_op(xc_handle, &op) < 0 ) + { xcio_error(ioctxt, "Could not get information on new domain"); goto out; } shared_info_frame = op.u.getdomaininfo.shared_info_frame; - if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 ) + if ( (pm_handle = init_pfn_mapper((domid_t)dom)) == NULL ) goto out; - - /* Build the pfn-to-mfn table. We choose MFN ordering returned by Xen. */ - if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) { - xcio_error(ioctxt, "Did not read correct number of frame numbers for new dom"); + if ( get_pfn_list(xc_handle, dom, pfn_to_mfn_table, nr_pfns) != nr_pfns ) + { + xcio_error(ioctxt, "Did not read correct number of frame " + "numbers for new dom"); goto out; } - if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) { + if ( (mmu = init_mmu_updates(xc_handle, dom)) == NULL ) + { xcio_error(ioctxt, "Could not initialise for MMU updates"); goto out; } @@ -238,33 +254,39 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) */ prev_pc = 0; - n=0; - while(1) { + n = 0; + while ( 1 ) + { int j; unsigned long region_pfn_type[MAX_BATCH_SIZE]; this_pc = (n * 100) / nr_pfns; - if ( (this_pc - prev_pc) >= 5 ) { + if ( (this_pc - prev_pc) >= 5 ) + { xcio_info(ioctxt, "\b\b\b\b%3d%%", this_pc); prev_pc = this_pc; } - if ( xcio_read(ioctxt, &j, sizeof(int)) ) { + if ( xcio_read(ioctxt, &j, sizeof(int)) ) + { xcio_error(ioctxt, "Error when reading from state file"); goto out; } DPRINTF("batch %d\n",j); - if ( j == -1 ) { + if ( j == -1 ) + { verify = 1; printf("Entering page verify mode\n"); continue; } - if ( j == 0 ) break; /* our work here is done */ + if ( j == 0 ) + break; /* our work here is done */ - if( j > MAX_BATCH_SIZE ) { + if ( j > MAX_BATCH_SIZE ) + { xcio_error(ioctxt, "Max batch size exceeded. Giving up."); goto out; } @@ -274,10 +296,14 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) goto out; } - for(i=0; inr_pfns) { + if (pfn>nr_pfns) + { xcio_error(ioctxt, "pfn out of range"); goto out; } @@ -309,32 +338,36 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) mfn = pfn_to_mfn_table[pfn]; - if ( verify ) { + if ( verify ) ppage = (unsigned long*) buf; /* debug case */ - } else { + else ppage = (unsigned long*) (region_base + i*PAGE_SIZE); - } - if ( xcio_read(ioctxt, ppage, PAGE_SIZE) ) { + if ( xcio_read(ioctxt, ppage, PAGE_SIZE) ) + { xcio_error(ioctxt, "Error when reading from state file"); goto out; } - switch( region_pfn_type[i] ) { + switch( region_pfn_type[i] ) + { case 0: break; case L1TAB: { - for ( k = 0; k < 1024; k++ ) { - if ( ppage[k] & _PAGE_PRESENT ) { + for ( k = 0; k < 1024; k++ ) + { + if ( ppage[k] & _PAGE_PRESENT ) + { xpfn = ppage[k] >> PAGE_SHIFT; - - if ( xpfn >= nr_pfns ) { - xcio_error(ioctxt, "Frame number in type %lu page table is " - "out of range. i=%d k=%d pfn=0x%lx " - "nr_pfns=%lu", region_pfn_type[i]>>28, i, - k, xpfn, nr_pfns); + if ( xpfn >= nr_pfns ) + { + xcio_error(ioctxt, "Frame number in type %lu page " + "table is out of range. i=%d k=%d " + "pfn=0x%lx nr_pfns=%lu", + region_pfn_type[i]>>28, i, + k, xpfn, nr_pfns); goto out; } @@ -350,15 +383,19 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) { for ( k = 0; k < (HYPERVISOR_VIRT_START>>L2_PAGETABLE_SHIFT); - k++ ) { - if ( ppage[k] & _PAGE_PRESENT ) { + k++ ) + { + if ( ppage[k] & _PAGE_PRESENT ) + { xpfn = ppage[k] >> PAGE_SHIFT; - if ( xpfn >= nr_pfns ) { - xcio_error(ioctxt, "Frame number in type %lu page table is " - "out of range. i=%d k=%d pfn=%lu nr_pfns=%lu", - region_pfn_type[i]>>28, i, k, xpfn, nr_pfns); - + if ( xpfn >= nr_pfns ) + { + xcio_error(ioctxt, "Frame number in type %lu page" + " table is out of range. i=%d k=%d " + "pfn=%lu nr_pfns=%lu", + region_pfn_type[i]>>28, i, k, + xpfn, nr_pfns); goto out; } @@ -371,21 +408,25 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) break; default: - xcio_error(ioctxt, "Bogus page type %lx page table is out of range." - " i=%d nr_pfns=%lu", region_pfn_type[i], i, nr_pfns); + xcio_error(ioctxt, "Bogus page type %lx page table is " + "out of range. i=%d nr_pfns=%lu", + region_pfn_type[i], i, nr_pfns); goto out; } /* end of page type switch statement */ - if ( verify ) { + if ( verify ) + { int res = memcmp(buf, (region_base + i*PAGE_SIZE), PAGE_SIZE ); - if (res) { + if ( res ) + { int v; printf("************** pfn=%lx type=%lx gotcs=%08lx " "actualcs=%08lx\n", pfn, pfn_type[pfn], csum_page(region_base + i*PAGE_SIZE), csum_page(buf)); - for ( v = 0; v < 4; v++ ) { + for ( v = 0; v < 4; v++ ) + { unsigned long *p = (unsigned long *) (region_base + i*PAGE_SIZE); if ( buf[v] != p[v] ) @@ -396,7 +437,8 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) } if ( add_mmu_update(xc_handle, mmu, - (mfn< 8192 ) { + if ( ctxt.gdt_ents > 8192 ) + { xcio_error(ioctxt, "GDT entry count out of range"); goto out; } - for ( i = 0; i < ctxt.gdt_ents; i += 512 ) { + for ( i = 0; i < ctxt.gdt_ents; i += 512 ) + { pfn = ctxt.gdt_frames[i]; - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) { + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) + { xcio_error(ioctxt, "GDT frame number is bad"); goto out; } @@ -478,7 +527,8 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* Uncanonicalise the page table base pointer. */ pfn = ctxt.pt_base >> PAGE_SHIFT; - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) { + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != L2TAB) ) + { printf("PT base is bad. pfn=%lu nr=%lu type=%08lx %08lx\n", pfn, nr_pfns, pfn_type[pfn], (unsigned long)L2TAB); xcio_error(ioctxt, "PT base is bad."); @@ -499,11 +549,13 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* Uncanonicalise the pfn-to-mfn table frame-number list. */ - for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) { + for ( i = 0; i < (nr_pfns+1023)/1024; i++ ) + { unsigned long pfn, mfn; pfn = pfn_to_mfn_frame_list[i]; - if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) { + if ( (pfn >= nr_pfns) || (pfn_type[pfn] != NOTAB) ) + { xcio_error(ioctxt, "PFN-to-MFN frame number is bad"); goto out; } @@ -515,15 +567,16 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) mfn_mapper_map_batch(xc_handle, dom, PROT_WRITE, pfn_to_mfn_frame_list, - (nr_pfns+1023)/1024 )) == 0 ) { + (nr_pfns+1023)/1024 )) == 0 ) + { xcio_error(ioctxt, "Couldn't map pfn_to_mfn table"); goto out; } - memcpy( live_pfn_to_mfn_table, pfn_to_mfn_table, - nr_pfns*sizeof(unsigned long) ); + memcpy(live_pfn_to_mfn_table, pfn_to_mfn_table, + nr_pfns*sizeof(unsigned long) ); - munmap( live_pfn_to_mfn_table, ((nr_pfns+1023)/1024)*PAGE_SIZE ); + munmap(live_pfn_to_mfn_table, ((nr_pfns+1023)/1024)*PAGE_SIZE); /* * Safety checking of saved context: @@ -538,20 +591,18 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) * 9. debugregs are checked by Xen. * 10. callback code selectors need checking. */ - for ( i = 0; i < 256; i++ ) { + for ( i = 0; i < 256; i++ ) + { ctxt.trap_ctxt[i].vector = i; if ( (ctxt.trap_ctxt[i].cs & 3) == 0 ) ctxt.trap_ctxt[i].cs = FLAT_GUESTOS_CS; } - if ( (ctxt.guestos_ss & 3) == 0 ){ + if ( (ctxt.guestos_ss & 3) == 0 ) ctxt.guestos_ss = FLAT_GUESTOS_DS; - } - if ( (ctxt.event_callback_cs & 3) == 0 ){ + if ( (ctxt.event_callback_cs & 3) == 0 ) ctxt.event_callback_cs = FLAT_GUESTOS_CS; - } - if ( (ctxt.failsafe_callback_cs & 3) == 0 ){ + if ( (ctxt.failsafe_callback_cs & 3) == 0 ) ctxt.failsafe_callback_cs = FLAT_GUESTOS_CS; - } if ( ((ctxt.ldt_base & (PAGE_SIZE - 1)) != 0) || (ctxt.ldt_ents > 8192) || (ctxt.ldt_base > HYPERVISOR_VIRT_START) || @@ -568,7 +619,8 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) /* don't start the domain as we have console etc to set up */ - if( rc == 0 ) { + if ( rc == 0 ) + { /* Success: print the domain id. */ xcio_info(ioctxt, "DOM=%lu\n", dom); return 0; @@ -576,25 +628,20 @@ int xc_linux_restore(int xc_handle, XcIOContext *ioctxt) out: - if ( (rc != 0) && (dom != 0) ){ + if ( (rc != 0) && (dom != 0) ) xc_domain_destroy(xc_handle, dom); - } - if ( mmu != NULL ){ + if ( mmu != NULL ) free(mmu); - } - if ( pm_handle >= 0 ){ + if ( pm_handle != NULL ) (void)close_pfn_mapper(pm_handle); - } - if ( pfn_to_mfn_table != NULL ){ + if ( pfn_to_mfn_table != NULL ) free(pfn_to_mfn_table); - } - if ( pfn_type != NULL ){ + if ( pfn_type != NULL ) free(pfn_type); - } - if ( rc == 0 ){ + if ( rc == 0 ) ioctxt->domain = dom; - } + DPRINTF("Restore exit with rc=%d\n",rc); return rc; } diff --git a/tools/libxc/xc_netbsd_build.c b/tools/libxc/xc_netbsd_build.c index 04a47b5068..833a533ab6 100644 --- a/tools/libxc/xc_netbsd_build.c +++ b/tools/libxc/xc_netbsd_build.c @@ -13,7 +13,7 @@ #define DPRINTF(x) #endif -static int loadelfimage(gzFile, int, unsigned long *, unsigned long, +static int loadelfimage(gzFile, void *, unsigned long *, unsigned long, unsigned long *, unsigned long *, unsigned long *, unsigned long *); @@ -77,9 +77,10 @@ static int setup_guestos(int xc_handle, shared_info_t *shared_info; unsigned long ksize; mmu_t *mmu = NULL; - int pm_handle, i; + void *pm_handle = NULL; + int i; - if ( (pm_handle = init_pfn_mapper((domid_t)dom)) < 0 ) + if ( (pm_handle = init_pfn_mapper((domid_t)dom)) == NULL ) goto error_out; if ( (page_array = malloc(tot_pages * sizeof(unsigned long))) == NULL ) @@ -201,7 +202,7 @@ static int setup_guestos(int xc_handle, error_out: if ( mmu != NULL ) free(mmu); - if ( pm_handle >= 0 ) + if ( pm_handle != NULL ) (void)close_pfn_mapper(pm_handle); if ( page_array == NULL ) free(page_array); @@ -412,7 +413,7 @@ myseek(gzFile gfd, off_t offset, int whence) #define IS_BSS(p) (p.p_filesz < p.p_memsz) static int -loadelfimage(gzFile kernel_gfd, int pm_handle, unsigned long *page_array, +loadelfimage(gzFile kernel_gfd, void *pm_handle, unsigned long *page_array, unsigned long tot_pages, unsigned long *virt_load_addr, unsigned long *ksize, unsigned long *symtab_addr, unsigned long *symtab_len) diff --git a/tools/libxc/xc_private.c b/tools/libxc/xc_private.c index 344f48254d..8807f8a9bf 100644 --- a/tools/libxc/xc_private.c +++ b/tools/libxc/xc_private.c @@ -6,51 +6,140 @@ #include "xc_private.h" -int init_pfn_mapper(domid_t domid) +#define MAX_EXTENTS 8 +typedef struct { + int fd; + struct { + void *base; + unsigned long length; + } extent[MAX_EXTENTS]; +} mapper_desc_t; + +void *init_pfn_mapper(domid_t domid) { - int fd = open("/dev/mem", O_RDWR); - if ( fd >= 0 ) - (void)ioctl(fd, _IO('M', 1), (unsigned long)domid); - return fd; + int fd = open("/dev/mem", O_RDWR); + mapper_desc_t *desc; + + if ( fd < 0 ) + return NULL; + + if ( (desc = malloc(sizeof(*desc))) == NULL ) + { + close(fd); + return NULL; + } + + (void)ioctl(fd, _IO('M', 1), (unsigned long)domid); + + memset(desc, 0, sizeof(*desc)); + desc->fd = fd; + + return desc; } -int close_pfn_mapper(int pm_handle) +int close_pfn_mapper(void *pm_handle) { - return close(pm_handle); + mapper_desc_t *desc = pm_handle; + int i; + + for ( i = 0; i < MAX_EXTENTS; i++ ) + { + if ( desc->extent[i].base != NULL ) + (void)munmap(desc->extent[i].base, desc->extent[i].length); + } + + close(desc->fd); + free(desc); + + return 0; } -void *map_pfn_writeable(int pm_handle, unsigned long pfn) +static int get_free_offset(mapper_desc_t *desc) { - void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, - MAP_SHARED, pm_handle, pfn << PAGE_SHIFT); + int i; + + for ( i = 0; i < MAX_EXTENTS; i++ ) + { + if ( desc->extent[i].base == NULL ) + break; + } + + if ( i == MAX_EXTENTS ) + { + fprintf(stderr, "Extent overflow in map_pfn_*()!\n"); + fflush(stderr); + *(int*)0=0; /* XXX */ + } + + return i; +} + +void *map_pfn_writeable(void *pm_handle, unsigned long pfn) +{ + mapper_desc_t *desc = pm_handle; + void *vaddr; + int off; + + vaddr = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, + MAP_SHARED, desc->fd, pfn << PAGE_SHIFT); if ( vaddr == MAP_FAILED ) return NULL; + + off = get_free_offset(desc); + desc->extent[off].base = vaddr; + desc->extent[off].length = PAGE_SIZE; + return vaddr; } -void *map_pfn_readonly(int pm_handle, unsigned long pfn) +void *map_pfn_readonly(void *pm_handle, unsigned long pfn) { - void *vaddr = mmap(NULL, PAGE_SIZE, PROT_READ, - MAP_SHARED, pm_handle, pfn << PAGE_SHIFT); + mapper_desc_t *desc = pm_handle; + void *vaddr; + int off; + + vaddr = mmap(NULL, PAGE_SIZE, PROT_READ, + MAP_SHARED, desc->fd, pfn << PAGE_SHIFT); if ( vaddr == MAP_FAILED ) return NULL; + + off = get_free_offset(desc); + desc->extent[off].base = vaddr; + desc->extent[off].length = PAGE_SIZE; + return vaddr; } -void unmap_pfn(int pm_handle, void *vaddr) +void unmap_pfn(void *pm_handle, void *vaddr) { - (void)munmap(vaddr, PAGE_SIZE); + mapper_desc_t *desc = pm_handle; + int i; + unsigned long len = 0; + + for ( i = 0; i < MAX_EXTENTS; i++ ) + { + if ( desc->extent[i].base == vaddr ) + { + desc->extent[i].base = NULL; + len = desc->extent[i].length; + } + } + + if ( len == 0 ) + *(int*)0 = 0; /* XXX */ + + (void)munmap(vaddr, len); } /*******************/ -void * mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot, - unsigned long *arr, int num ) +void *mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot, + unsigned long *arr, int num ) { privcmd_mmapbatch_t ioctlx; void *addr; - addr = mmap( NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0 ); - if (addr) + addr = mmap(NULL, num*PAGE_SIZE, prot, MAP_SHARED, xc_handle, 0); + if ( addr != NULL ) { ioctlx.num=num; ioctlx.dom=dom; @@ -69,15 +158,15 @@ void * mfn_mapper_map_batch(int xc_handle, domid_t dom, int prot, /*******************/ -void * mfn_mapper_map_single(int xc_handle, domid_t dom, - int size, int prot, - unsigned long mfn ) +void *mfn_mapper_map_single(int xc_handle, domid_t dom, + int size, int prot, + unsigned long mfn ) { privcmd_mmap_t ioctlx; privcmd_mmap_entry_t entry; void *addr; - addr = mmap( NULL, size, prot, MAP_SHARED, xc_handle, 0 ); - if (addr) + addr = mmap(NULL, size, prot, MAP_SHARED, xc_handle, 0); + if ( addr != NULL ) { ioctlx.num=1; ioctlx.dom=dom; @@ -85,7 +174,7 @@ void * mfn_mapper_map_single(int xc_handle, domid_t dom, entry.va=(unsigned long) addr; entry.mfn=mfn; entry.npages=(size+PAGE_SIZE-1)>>PAGE_SHIFT; - if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) <0 ) + if ( ioctl( xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx ) < 0 ) { munmap(addr, size); return 0; diff --git a/tools/libxc/xc_private.h b/tools/libxc/xc_private.h index 742185161b..aff7a80463 100644 --- a/tools/libxc/xc_private.h +++ b/tools/libxc/xc_private.h @@ -131,11 +131,11 @@ static inline int do_multicall_op(int xc_handle, /* * PFN mapping. */ -int init_pfn_mapper(domid_t domid); -int close_pfn_mapper(int pm_handle); -void *map_pfn_writeable(int pm_handle, unsigned long pfn); -void *map_pfn_readonly(int pm_handle, unsigned long pfn); -void unmap_pfn(int pm_handle, void *vaddr); +void *init_pfn_mapper(domid_t domid); +int close_pfn_mapper(void *pm_handle); +void *map_pfn_writeable(void *pm_handle, unsigned long pfn); +void *map_pfn_readonly(void *pm_handle, unsigned long pfn); +void unmap_pfn(void *pm_handle, void *vaddr); int get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr); unsigned long csum_page (void * page);